#!/usr/bin/python2.4


import constants
import flags
from logger import logger, rpc_logger
import scheduler
from rpc_stubs import afe, tko
import test_results
import utils


flags.add_option('--show-results', '--sr', action='store_true')
flags.add_option('--show-status', '--ss', action='store_true')
flags.add_option('--show-stats', '--st', action='store_true')
flags.add_option('--show-run-stats', '--srt', action='store_true')
flags.add_option('--no-show-schedules', '--nosc', action='store_false',
                 dest='show_schedules', default=True)
flags.add_option('--no-log-host-stats', '--nolht', action='store_false',
                 dest='log_host_stats', default=True)


class Oracle(object):

  def __init__(self, test_plan, inspector_path=None):
    self.test_plan = test_plan
    self.test_results = test_results.TestResults(test_plan, inspector_path)
    self.scheduler = scheduler.Scheduler(self.test_results)

  def __repr__(self):
    results = '%s(name=%r, %d tests' % (type(self).__name__,
                                        self.test_plan.name,
                                        len(self.test_plan.tests))
    if self.test_plan.hosts is not None:
      results += ', %d hosts' % len(self.test_plan.hosts)
    if self.test_results.job_host_runs is not None:
      results += ', %d runs' % len(self.test_results.job_host_runs)
    results += ')'
    return results

  def setup(self, query_hosts=True, query_results=True):

    def create_label_if_not_exist(rpc, label):
      if rpc is afe:
        get_op, add_op = 'get_labels', 'add_label'
        get_dargs = {'invalid': False}
      elif rpc is tko:
        get_op, add_op = 'get_test_labels', 'add_test_label'
        get_dargs = {}
      else:
        rpc_logger.fatal('rpc object is not afe or tko')

      labels = rpc.run(get_op, name=label, **get_dargs)
      if len(labels) == 1:
        return False

      rpc.run(add_op, label)
      return True

    create_label_if_not_exist(afe, constants.HL_TRIAGE_NEEDED)
    for label in constants.ALL_TL_LABELS:
      create_label_if_not_exist(tko, label)
    self.test_plan.setup(query_hosts=query_hosts or query_results)
    self.test_results.setup(query_results=query_results, update_hosts=False)
    self.scheduler.setup()

  def run_once(self, schedule_only=False, dry_run=False):

    def log_schedules(schedules, level=logger.ERROR):
      if schedules:
        logger.logging(level, 'Schedules:\n%s' % '\n'.join(
            " run '%s'(%s) on %s" % (job_name, infix,
                                     utils.pformat_array(hostnames))
            for job_name, hostnames, infix in schedules))
        return True
      return False

    if not schedule_only:
      self.test_results.get_results(update_hosts=True)

    logger.error('Total %d hosts, processing %d hosts' %
                 (len(self.test_plan.hosts), len(self.test_results.hosts)))

    if flags.get_option('show_results'):
      self.test_results.log_results()

    if not schedule_only:
      self.test_results.compute_stats()

    if flags.get_option('show_status'):
      self.test_results.log_status()

    if flags.get_option('show_stats'):
      self.test_results.log_stats(
          include_hosts=flags.get_option('log_host_stats'))
    else:
      logger.error(self.test_results.overall_stats.pformat())

    if not schedule_only:
      self.test_results.compute_run_stats()

    if flags.get_option('show_run_stats'):
      self.test_results.log_run_stats(
          include_hosts=flags.get_option('log_host_stats'))
    else:
      logger.error(self.test_results.overall_run_stats.pformat())

    schedules = self.scheduler.get_schedules()

    if flags.get_option('show_schedules', True):
      log_schedules(schedules)


    jobs = []
    if not dry_run:
      for job_name, hostnames, infix in schedules:
        job_id = self.test_plan.create_job(job_name, hostnames, infix)
        jobs.append((job_name, hostnames, infix, job_id))
    elif schedules:
      logger.error('DRY RUN, NO ACTIONS ARE TAKEN')
    return jobs
